<?php
/*
 * Created on Feb 5, 2009
 *
 * To change the template for this generated file go to
 * Window - Preferences - PHPeclipse - PHP - Code Templates
 */
class place_Model_Place extends Clu_Db_Table_Abstract
{
    //only specify the table name, everything else inherits
	protected $_name = "places";
	protected $_primary = "id";
	
	public function findByPrimary($id)
	{
		if (!$id)
            return null;
        else
		    return $this->fetchRow('id = ' . $this->getAdapter()->quote($id, 'INTEGER'));
	}
	
	public function updateDbAfterInsertOrDelete($cityId,$districtId,$check)
	{
		//$check = 1 insert ; $check = 0 delete
		try{
			
			$mCity = new place_Model_City();
			$city = $mCity->findByPrimary($cityId);
			$metadataCity = unserialize($city['metadata']);
			if($check == 1)
				$metadataCity['number_of_places'] = (integer) $metadataCity['number_of_places'] + 1;
			else
				$metadataCity['number_of_places'] = (integer) $metadataCity['number_of_places'] - 1;
			$city['metadata'] = $metadataCity;
			$city['metadata'] = serialize($city['metadata']);
			$city->save();
		}
		catch (Exception $e)
		{
			$db->rollBack();
			$this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(903);
		}
		
		if($districtId)
		{
			try{
			
			$mDistrict = new place_Model_District();
			$district = $mDistrict->findByPrimary($districtId);
			$metadataDistrict = unserialize($district['metadata']);
			if($check == 1)
				$metadataDistrict['number_of_places'] = (integer) $metadataDistrict['number_of_places'] + 1;
			else
				$metadataDistrict['number_of_places'] = (integer) $metadataDistrict['number_of_places'] - 1;
			$district['metadata'] =  $metadataDistrict;
			$district['metadata'] = serialize($district['metadata']);
			
			$district->save();
			}
			catch(Exception $e)
			{
				$db->rollBack();
	            $this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(904);
			}
		}
	}
	
	public function insertRaw($data, $options = array('do_validate' => false))
	{
		$keys = array('name','city_id','district_id','village_id',
                      'article_id','type','rtype','longitude',
                      'latitude','address5','address6', 'address7', 'address8',
        	          'address9','other_name', 'status', 'poster_id', 'metadata');
        $t = clu_array_merge($keys, $data);
        
        $t['unaccented_name'] = VN_unaccent($t['name']);
        //get address name
	    if(isset($t['type']))
        	$t['type'] = implode(',', $t['type']);
        $getAddressName = $this->getData($id = null, $t);
        $a['city_name'] = $getAddressName['city_name'];
        $a['district_name'] = $getAddressName['district_name'];
        $a['village_name'] = $getAddressName['village_name'];
        $a['rtype_name'] = $getAddressName['category_name'];
        if(!empty($getAddressName['type_name']))
        {
	        foreach($getAddressName['type_name'] as $k => $v)
	        	$a['type_name'][$k] = $v;
        }
        
        $auth = Zend_Auth::getInstance();
       	$uIdentity = $auth->getIdentity();
        $a['poster_name'] = $uIdentity->name;
        $t['metadata'] = serialize($a);
        
//       	return $this->insert($t);
		try 
		{
			$ret = $this->insert($t);
			if(isset($t['type']))
				$type = $t['type'];
			else
				$type = null;
			if(isset($t['district_id']))
				$districtId = $t['district_id'];
			else
				$districtId = null;
				
			$this->updateDbAfterInsert($t['city_id'], $districtId, $t['rtype'], $type);
//			$this->updateDbAfterInsertOrDelete($t['city_id'], $t['district_id'],true);
		  	return $ret;
		}
		catch (Exception $e)
		{
		 	echo $e->getMessage();
		}
		
	}
	
	public function saveRaw($a, $data, $id, $options = array('do_validate' => false))
    {
        if ((!$a) && (!$id))
            return false;
        else if (!$a)
            if(!$a = $this->findByPrimary($id))
                return false;
	    
        if ($options['do_validate'])
	    {
	    	//Validate Data here
	    }
	    
	    if(!empty($data['name']) && !isset($data['other_article_id']))
	    	$data['unaccented_name'] = VN_unaccent($data['name']);
	    if(isset($data['article_body']) && !isset($data['other_article_id']))
	    	$data['desc'] = $data['article_body'];

	    if(!empty($data['payment_method']))
	    	$data['payment_method'] = implode(',', $data['payment_method']);
	    	
        if(isset($data['place_id']))
        	$data['place_id'] = $data['place_id'];
        $metadata = $this->getMetadata($a, $data);
        
        $data['metadata'] = serialize($metadata);
        if(isset($data['meals']))
        	$data['meals'] = implode(',', $data['meals']);
        	
        $data['update_time'] = time();
        // insert vicinity places
		if ((!isset($data['tour_id']) || !isset($data['event_id'])) && isset($data['belong_to_ids']) && !empty($data['belong_to_names_submit']))
		{
	    	$belong_to_ids = explode(',', $data['belong_to_ids']);
	    	$belongToNames = explode(',', $data['belong_to_names_submit']);
	    	$distances = explode(',', $data['distance']);
			
	    	$vicinityPlaces = array(); //a 'place_vicinities' table row
	    	foreach($belong_to_ids as $i => $vicinityPlaceId)
	    	{
	    		$vicinityPlaces[$i]['vicinity_place_id'] = $vicinityPlaceId;
	    		$vicinityPlaces[$i]['vicinity_place_name'] = $belongToNames[$i];
	    		$vicinityPlaces[$i]['distance'] = $distances[$i];
	    		$vicinityPlaces[$i]['place_id'] = $id;
	    		$vicinityPlaces[$i]['place_name'] = $a->name;
	    	}
	    	
			foreach($vicinityPlaces as $i=>$vicinityPlace)
			{
				$mVicinity = new place_Model_Vicinity();
				$vicinityPlace['vicinity_place_type'] = $data['rtype'];
				
				try
				{
					//$mVicinity->saveRaw($a, $vicinityPlace, $id, false);
					$mVicinity->insertRaw($vicinityPlace, false); //no need to validate
				}
				catch (Exception $e)
				{
					//do nothing
					//die($e->getMessage());
				}
			}								
		}
		else if(!isset($data['event_id']) || !isset($data['tour_id']))
		{
			$mVicinity = new place_Model_Vicinity();
			$mVicinity->deleteByPrimary($id);
		}
		
    	//return $a->save();
        try 
		{
			
			if(isset($data['type']))
				$type = $data['type'];
			else
				$type = null;
				
			if(isset($a->district_id))
				$districtId = $a->district_id;
			else
				$districtId = null;
			
			$this->updateDbAfterUpdate($a, $a->city_id, $districtId, $data['rtype'], $type);
	        $a->setFromArray($data);
		  	return $a->save();
		}
		catch (Exception $e)
		{
		 	echo $e->getMessage();
		}
        
    }

	public function getMetadata ($row, $data)
	{
		$metadata =array();
		if(isset($row->metadata))
        	$dbMeta = unserialize($row->metadata);
		
        $keys = array('city_name', 'district_name', 'related_event_id',
        			'village_name', 'rtype_name', 'poster_name', 'article_title', 'article_language',
        			'type_name', 'contact_email','fax', 'website','phone'
        			);
			
	    $mCity = new place_Model_City();
        $mDistrict = new place_Model_District();
        $mVillage = new place_Model_Village();
    	if(isset($data['city_id']))
    	{
        	$cityName = $mCity->getCityName($data['city_id']);
	        $metadata['city_name'] = $cityName['city_name'];
    	}
    	else if (isset($dbMeta['city_name']))
    		$metadata['city_name'] = $dbMeta['city_name'];
    		
    	if(isset($data['district_id']))
    	{
	        $districtName = $mDistrict->getDistrictName($data['district_id']);
	        $metadata['district_name'] = $districtName['district_name'];
    	}
    	else if (isset($dbMeta['district_name']))
    		$metadata['district_name'] = $dbMeta['district_name'];
    		
    	if(isset($data['village_id']))
    	{
	        $villageName = $mVillage->getVillageName($data['village_id']);
	        $metadata['village_name'] = $villageName['village_name'];
    	}
    	else if (isset($dbMeta['village_name']))
    		$metadata['village_name'] = $dbMeta['village_name'];
    		
    	if(isset($data['rtype']))
    	{
    		$mCategory = new category_Model_Category();
    		$mCategory->setTables('place');
	        $rtypeName = $mCategory->getCategoryName($data['rtype']);
	        $metadata['rtype_name'] = $rtypeName['name'];
    	}
    	else if (isset($dbMeta['rtype_name']))
    		$metadata['rtype_name'] = $dbMeta['rtype_name'];
    		
    	if(isset($data['type']))
    	{
    		//$a = explode(',', $data['type']);
    		$mCategory = new category_Model_Category();
    		$mCategory->setTables('place');
    		//foreach($a as $k => $v)
		        $typeName = $mCategory->getCategoryName($data['type']);
	        $metadata['type_name'] = $typeName['name'];
    	}
    	else if (isset($dbMeta['type_name']))
    		$metadata['type_name'] = $dbMeta['type_name'];
    	
        if( isset($data['contact_email']) || isset($data['website']) || 
        	isset($data['fax']) || isset($data['phone']))
        {
	        $metadata['contact_email'] = $data['contact_email'];
	        $metadata['website'] = $data['website'];
	        $metadata['fax'] = $data['fax'];
	        $metadata['phone'] = $data['phone'];
        }
        else if (isset($dbMeta['contact_email']) || isset($dbMeta['website']) ||
        		isset($dbMeta['fax']) || isset($dbMeta['phone']))
        {
        	$metadata['contact_email'] = $dbMeta['contact_email'];
	        $metadata['website'] = $dbMeta['website'];
	        $metadata['fax'] = $dbMeta['fax'];
	        $metadata['phone'] = $dbMeta['phone'];
        }
		
        if(isset($dbMeta['poster_name']))
        {
        	/*$auth = Zend_Auth::getInstance();
	       	$uIdentity = $auth->getIdentity();
	        $metadata['poster_name'] = $uIdentity->name;
			*/
        	$metadata['poster_name'] = $dbMeta['poster_name'];
        }
        //hack to update poster_name to metadata.
        //the code before only inserted poster_id without writing the 
        //poster_name to metadata;
        /*
        $uModel = new user_Model_User();
        $user =  $uModel->getUserData($data['poster_id']);
        $metadata['poster_name'] = $user->name;
		*/
		if(isset($data['event_id']))
		{
			if(isset($dbMeta['related_tour_id']))
				$metadata['related_tour_id'] = $dbMeta['related_tour_id'];
			//delete related_event_id and updated list of related_event_id
			if(isset($data['place_id']))
			{
				$relatedEventId = explode(',', $dbMeta['related_event_id']);
				if(count($relatedEventId) > 1)
				{
					foreach($relatedEventId as $e)
						if($data['event_id'] != $e)
							$a[] = $e;
					$event_id = implode(',', $a);
					$metadata['related_event_id'] = $event_id;
				}
				else 
				{
					$metadata['related_event_id'] = null;
				}	
			}
			else // add related_event_id
			{
				if(!isset($dbMeta['related_event_id']))
					$metadata['related_event_id'] = $data['event_id'];
				else /*if($data['event_id'] != 1)*/
					$metadata['related_event_id'] = $dbMeta['related_event_id'] . ',' . $data['event_id'];
			}
		}
		
		if(isset($data['tour_id']))
		{
			if(isset($dbMeta['related_event_id']))
				$metadata['related_event_id'] = $dbMeta['related_event_id'];
			/**
			 * delete related_tour_id
			 */
			//delete related_tour_id and updated list of related_tour_id
			if(isset($data['place_id']))
			{
				if(isset($dbMeta['related_tour_id']))
				{
					$relatedTourId = explode(',', $dbMeta['related_tour_id']);
					if(count($relatedTourId) > 1)
					{
						foreach($relatedTourId as $e)
							if($data['tour_id'] != $e)
								$a[] = $e;
						$tour_id = implode(',', $a);
						$metadata['related_tour_id'] = $tour_id;
					}
					else if($data['tour_id'] == $dbMeta['related_tour_id'])
						$metadata['related_tour_id'] = $dbMeta['related_tour_id'];
				}
				else
					$metadata['related_tour_id'] = $data['tour_id'];
			}
			else // add related_tour_id
			{
				if(!isset($dbMeta['related_tour_id']))
					$metadata['related_tour_id'] = $data['tour_id'];
				else
				{
					if($data['tour_id'] != $dbMeta['related_tour_id'])
						$metadata['related_tour_id'] = $dbMeta['related_tour_id'] . ',' . $data['tour_id'];
					else
						$metadata['related_tour_id'] = $dbMeta['related_tour_id'];
				}
				
			}
		}
		if(!isset($data['remove']))
		{
			if(isset($data['other_article_id']))
			{
				//add new article && update article
				if(!isset($data['edit']))
				{
					$otherArticleIds = explode(',', $data['other_article_id']);
					$other_article = array();
					foreach($otherArticleIds as $key)
						$other_article[] = array('weight' => $data['article_weight'],
												'other_article_id' => $key,
											   'article_title' => array('title' => $data['name'],
											   							'language' => $data['article_language'],
											   							),
											   'poster_id' => $data['poster_id'],
											  );
					
					if(isset($dbMeta['other_article']))
					{
						foreach($dbMeta['other_article'] as $k => $ats)
							$other_article[] = $ats;
					}
					
					$metadata['other_article'] = $other_article;
				}
				else
				{
					foreach($dbMeta['other_article'] as $k => $ats)
					{
						if($data['other_article_id'] == $ats['other_article_id'])
						{
							$dbMeta['other_article'][$k]['weight'] = $data['article_weight'];
							$dbMeta['other_article'][$k]['other_article_id'] = $data['other_article_id'];
							$dbMeta['other_article'][$k]['article_title']['title'] = $data['name'];
							$dbMeta['other_article'][$k]['article_title']['language'] = $data['article_language'];
							$dbMeta['other_article'][$k]['poster_id'] = $data['poster_id'];
						}
					}

					$metadata = $dbMeta;
				}
				
			}
			elseif(isset($dbMeta['other_article']))
			{
				$metadata['other_article'] = $dbMeta['other_article'];
			}
		}
		else
		{
			//delete metadata
			if(isset($dbMeta['other_article']))
			{
				foreach($dbMeta['other_article'] as $k => $ats)
					if($data['other_article_id'] == $ats['other_article_id'])
					{
						unset($dbMeta['other_article'][$k]);
						break;
					}
					$metadata['other_article'] = $dbMeta['other_article'];
			}
		}
		
//		die_a($metadata);
        return $metadata;
	}    
    
    public function deleteByPrimary($id, $atomic = true)
	{
		//check rights
        $auth = Zend_Auth::getInstance();
       	$uIdentity = $auth->getIdentity();
       	$p = $this->findByPrimary($id);
		$sess = new Zend_Session_Namespace(CLU_NS);
		if (($uIdentity->id != $p->poster_id && strpos ($sess->userPermissions, 'delete place') === false) || 
			($uIdentity->id == $p->poster_id && strpos ($sess->userPermissions, 'delete place') === false))
		{
				return false;
		}
		else 
		{
			$article_id = $p->article_id;
			$placeId = $p->id;
			$aModel = new article_Model_Service();
			$vModel = new place_Model_Vicinity();
			$db = $this->getAdapter();
	       	$db->beginTransaction();
	        try {
	        	$aModel->deleteByPrimary($article_id, false);
				$vModel->deleteByPrimary($placeId);
				$delete = $this->delete('id IN ('.$this->getAdapter()->quote($placeId, 'INTEGER').')');
				if($atomic)
					$db->commit();
				//$this->updateDbAfterInsertOrDelete($p['city_id'], $p['district_id'],false);
				$this->updateDbAfterDelete($p->city_id, $p->district_id,$p->rtype, $p->type);
				return true;
	        }
			catch (Exception $e)
			{
				$db->rollBack();
				return false;
			}
		}
	}
	
	public function deleteListByPrimary($idArray, $atomic = true)
	{
		$aModel = new article_Model_Service();
		$vModel = new place_Model_Vicinity();
		$db = $this->getAdapter();
		if ($atomic)
       		$db->beginTransaction();
        try {
			  
        	$articleIds = array();
        	foreach ($idArray as $placeId)
        	{
        		$tmp = $this->findByPrimary($placeId);
        		//$this->updateDbAfterInsertOrDelete($tmp['city_id'], $tmp['district_id'],false);
        		$this->updateDbAfterDelete($tmp->city_id, $tmp->district_id,$tmp->rtype, $tmp->type);
        		$articleIds[] = $tmp->article_id;
        	}	
			
			$aModel->deleteByPrimary($articleIds, false);
			$sql1 = "DELETE FROM place_vicinities WHERE place_id IN (". $db->quote($idArray, 'INTEGER') .")" ;
           	$db->query($sql1);
           	$sql2 = "DELETE FROM places WHERE id IN (". $db->quote($idArray, 'INTEGER') .")" ;
           	$db->query($sql2);
			if($atomic)
				$db->commit();
			return true;
        }
		catch (Exception $e)
		{
			if($atomic)
				$db->rollBack();
			return false;
		}
	}
	
	public function bulkUpdateStatus($idArray, $data)
    {
        $idList = implode (',', $idArray);
        $db = $this->getAdapter() ;
        $db->beginTransaction();
        try {
                $sql = "UPDATE places SET status = ".$db->quote($data['status'],'STRING')." WHERE id IN (".$idList.")" ;
	            $db->query($sql);
                $sql1 =  "UPDATE articles a, places p SET a.article_status = p.status WHERE a.article_id = p.article_id" ;
                $db->query($sql1);
	            $db->commit();
                return true;
        }    
        catch (Exception $e)
        {
            $db->rollBack();
            return false;
        }           
     }
     
	public function search($data)
	{
		$keys = array('language', 'id', 'name','city_id','district_id','village_id','unaccented_name',
                      'article_id','type','rtype','str_number','fee','to_fee', 'other_name',
                      'fee_basis','fee_currency','payment_method', 'meals', 'delivery',
        	          'built_year','to_built_year', 'status', 'str_name','rating', 'desc',
        	          'rating_count', 'asc_or_desc', 'orderBy', 'poster_id', 'getArticle', 'has_thumb', 'metadata', 'weight');
        //the search condition
		$t = clu_array_merge($keys, $data);
    	// Create the Zend_Db_Select object
    	$db = $this->getAdapter();
    	$select = new Zend_Db_Select($db);
		$select = $db->select();
        // Add a FROM clause
        /*
        $select->from( array('p' => 'places'), 
        			   array('id','name', 'city_id', 'district_id','longitude', 'latitude', 'type', 'poster_id', 
							 'fee', 'fee_basis', 'fee_currency', 'status', 'desc', 'rtype', 'metadata', 'article_id') );
		*/
        $select->from( array('p' => 'places')); 

    	if($t['language'] && $t['language'] != 'all')
    		$select->where('p.language = ?', $db->quoteinto($t['language'],'STRING'));
    	
		if($t['name'])
		{
			$strName = $t['name'];
			/*
			$keywords = preg_split ("/[\s,]+/", "$strName");
			$s = "p.name like " . "'%$strName%' ";
			if(count($keywords) > 1)
			{
				foreach($keywords as $v )
				{
					$name = strtolower(VN_unaccent(trim($v)));
					$s .= "OR " . strtolower(VN_unaccent(trim('p.name'))) ." like '%$v%' ";
				}
			}
        	$select->where($s);
        	*/
        	$select->where('p.unaccented_name LIKE ?',$db->quoteinto("%$strName%","STRING"));
			//$select->where('p.unaccented_name = ?',$db->quoteinto("$strName","STRING"));
		}
        	
        // Add a WHERE clause  $db->quote($parentId,'INT')
        if($t['city_id'])
        	$select->where('p.city_id = ?',(int)$db->quote($t['city_id'],"INT"));
        	
    	if($t['district_id'])
    	{	
    		if(!is_array($t['district_id']))
    			$district_Id = explode(',', $t['district_id']);
    		else
    			$district_Id = $t['district_id'];
    		foreach($district_Id as $dis)
    	 		$s = "p.district_id rlike '(^|,)".$dis."($|,)'";
    	 	$select->where($s);
    	}
        	
//        if($t['village_id'])
//        	$select->where('p.village_id = ?',(int)$db->quote($t['village_id'],"INT"));
        	
        if(!empty($t['rtype']))
        {
        	 if(count($t['rtype']) > 1)
        	 {
        	 	$s = 1;
        	 	foreach($t['rtype'] as $v )
        	 	{
        	 		$s .= " OR p.rtype = " . (int)$db->quote($v,"INT");
        	 	}
        	 	$select->where($s);
        	 }
             else
             { 
	        	$select->where('p.rtype = ?',(int)$db->quote($t['rtype'],"INT"));
             }
        }
        if(!empty($t['type']))
        {
        	if(!is_array($t['type']))
        		$type = explode(',', $t['type']);
        	else
        		$type = $t['type'];
    	 	foreach($type as $v )
    	 		$s = "p.type rlike '(^|,)".$v."($|,)'";
    	 	$select->where($s);
        }
        
        if($t['fee'])
        {
	        $select->where('p.fee >= ?', (float)$db->quote($t['fee'],"FLOAT"))
	               ->where('p.fee <= ?', (float)$db->quote($t['to_fee'],"FLOAT"));
        }
        
        if($t['fee_basis'])
        	$select->where('p.fee_basis = ?', $db->quoteinto($t['fee_basis'],"STRING"));
        
        if($t['fee_currency'])
        	$select->where('p.fee_currency = ?', $db->quoteinto($t['fee_currency'],"STRING"));
        
    	$s = "1 ";
        if($t['payment_method'])
        {
			foreach($t['payment_method'] as $pm)
				$s .= " AND " . $db->quoteinto("find_in_set(?,p.payment_method)", $pm);
			$select->where($s);
        }
        
        if($t['meals'])
        {
        	foreach($t['meals'] as $meal)
        		$s .= " AND " . $db->quoteinto("find_in_set(?,p.meals)", $meal);
        	$select->where($s);
        }
        
        if($t['delivery'])
        	$select->where('p.delivery = ?', (int)$db->quote($t['delivery']));
                   
        if($t['built_year'])
        {
        	$startBuiltYear = string_to_date($t['built_year']);
        	$finishBuiltYear = string_to_date($t['to_built_year']);
        	$select->where('p.built_year >= ?', $db->quoteinto($startBuiltYear,"STRING"))
                   ->where('p.built_year <= ?', $db->quoteinto($finishBuiltYear,"STRING"));
        }
        if($t['str_number'])
        	$select->where('p.str_number = ?', $db->quoteinto($t['str_number'],"STRING"));
        
        if($t['str_name']) //see db.txt
        	$select->where('p.address7 = ?', $db->quoteinto($t['str_name'],"STRING"));
        	
		//get Article:
        if($t['getArticle'])
		{
			$select->join(array('a' => 'articles'), 'a.article_id = p.article_id', array('a.article_id','a.article_title', 'a.article_status', 
																						 'a.article_body', 'article_language'));
			$select->where('a.article_id = p.article_id');
        }	
        
        //userID
        if($t['poster_id'])
		{
			$select->where('p.poster_id =?', (int)$db->quote($t['poster_id'], "INT"));
        }	
        
        if($t['status'])
        	$select->where('p.status = ?', $db->quoteinto($t['status'],"STRING"));
        	
		// Add an ORDER BY clause
        if($t['rating'])
        	$select->where('p.rating = ?', (int)$db->quote($t['rating'],"INT"));
        
        if($t['rating_count'])
        	$select->where('p.rating_count = ?', (int)$db->quote($t['rating_count'],"INT"));
        
        if (isset($t['has_thumb']) && $t['has_thumb'])
        {
        	$select->where('p.thumb is not null');
        }
        
        switch($t['orderBy'])
        {
            case 'rating':{
           	    $select->order(array(sprintf('p.rating %s',$db->quoteinto($t['asc_or_desc'],'STRING'))));
                break;
            }
            case 'rating_count':{
                $select->order(array(sprintf('p.rating_count %s',$db->quoteinto($t['asc_or_desc'],'STRING'))));
                break;
            }
        }
        
        if($t['id'])
        	$select->where('p.id = ?', (int)$db->quote($t['id'], "INT"));
        
        $select->order('p.city_id')
        	   ->order('p.weight');
         	   //->order('p.district_id');
	    $select->order('p.update_time DESC');
//        die_a($select->__toString());
		return $select;
	}
	
	/**
	 * @param $getArticle::Boolean
	 * 		if true: get the place description from 'articles' table
	 * 		else: get only data from 'places' table.
	 */
	public function getData($id, $options)
	{
		if ($place = $this->findByPrimary($id))
		{
			$ret = $place->toArray();
			if ($options['get_article'])
			{
				$article = new article_Model_Service();
				$ret['article'] = $article->findByPrimary($place['article_id']);//->toArray();
			}
			if ($options['get_vicinities'])
			{
				$vicinity = new place_Model_Vicinity();
				$ret['vicinities'] = $vicinity->getVicinitiesByPlaceId($id); 
			}
			
			if(isset($ret['article_id']))
	        {
		        $mArticle = new article_Model_Service();
		        $ret['article_data'] = $mArticle->getArticleData($ret['article_id']);
	        }
			//get category name
	        $mCategory = new category_Model_Category();
			$mCategory->setTables('place');
	        if(isset($ret['rtype']))
	        	$ret['category_name'] = $mCategory->getCategoryName($ret['rtype']);
	        if(isset($ret['type']))
	        {
		        $a = explode(',', $ret['type']);
		        foreach($a as $k => $v)
	        		$typeName[] = $mCategory->getCategoryName($v);
	        	$ret['type_name'] = $typeName;
	        }
			$metadata = unserialize($ret['metadata']);
			if(isset($metadata['city_name']))
				$ret['city_name'] = $metadata['city_name'];
			if(isset($metadata['district_name']))
				$ret['district_name'] = $metadata['district_name'];
			if(isset($metadata['village_name']))
				$ret['village_name'] = $metadata['village_name'];
//			die_a($ret);
	        	
			return $ret;
		}
		else
		{
			$ret = array();
			//get category name
	        $mCategory = new category_Model_Category();
			$mCategory->setTables('place');
	        if(isset($options['rtype']))
	        {
	        	$categoryName = $mCategory->getCategoryName($options['rtype']);
	        	$ret['category_name'] = $categoryName['name'];
	        }
	        if(isset($options['type']))
	        {
		        $a = explode(',', $options['type']);
		        foreach($a as $k => $v)
	        		$typeName[] = $mCategory->getCategoryName($v);
	        	foreach($typeName as $t)
		        	$r[] = $t['name'];
	        	$ret['type_name'] = $r;
	        }
			
			if(isset($options['city_id']))
			{
				$mCity = new place_Model_City();
				$cityName = $mCity->getCityName($options['city_id']);
				$ret['city_name'] = $cityName['city_name'];
			}	
			if (isset($options['district_id']))
		    {
		       	$mDistrict = new place_Model_District();
		    	$districtName = $mDistrict->getDistrictName($options['district_id']);
		    	$ret['district_name'] = $districtName['district_name'];
	        }
	        
	    	if (isset($options['village_id']))
		    {
				$mVillage = new place_Model_Village();
			    $villageName = $mVillage->getVillageName($options['village_id']);
			    $ret['village_name'] = $villageName['village_name'];
	        }
	        
			return $ret;
		}
			
	}
	
	public function updateDbAfterView($id)
	{
		$sql = sprintf("UPDATE `places` set `views`=`views`+1 WHERE `id`='%d'", $id);
		$db = Zend_Db_Table::getDefaultAdapter();
		$db->query($sql);
	}
	
	public function getTypePlaceCategory($id)
	{
		//getCategory && cache in $_SESSION
        $categories = $this->mCategory->getRootType('Root_Place');
        foreach($categories as $cat)
        {
        	$ret = $this->mCategory->getTree($cat['id'], 1, 1);
	       	$sess = new Zend_Session_Namespace("category");
	       	$sess->place_category = array("category_params" => $ret);
        }
        
	}
	
	public function transformToFormArray($formName, $row)
	{
        $t = array();
		//TODO:
		if($formName == 'place_Form_Place')
		{
			$t['article_id'] = $row->article_id;
			$mArticle = new article_Model_Service();
	        $a = $mArticle->getArticleData($t['article_id']);
        	$t['name'] = $a['article_title'];
        	$t['language'] = $a['article_language'];
		}
		
		else if($formName == 'place_Form_EditPlace')
		{
			if(isset($row->article_id))
	        {
		        $mArticle = new article_Model_Service();
		        $a = $mArticle->getArticleData($row->article_id);
		        if($a['article_body'] != 'NULL')
		        	$t['article_body'] = $a['article_body'];
	        }
			
			if(isset($row->meals))
				$t['meals'] = explode(',', $row->meals);
	    	if(isset($row->payment_method) && !is_array($row->payment_method))
		    	$t['payment_method'] = explode(',',$row->payment_method);
			if(isset($row->area))
				$t['area'] = $row->area;
			if(isset($row->fee))
				$t['fee'] = $row->fee;
			if(isset($row->fee_basis))
				$t['fee_basis'] = $row->fee_basis;
			if(isset($row->fee_currency))
				$t['fee_currency'] = $row->fee_currency; 
			if(isset($row->fee_currency))
				$t['built_year'] = $row->built_year; 
			if(isset($row->fee_currency))
				$t['festive_days_from'] = $row->festive_days_from; 
			if(isset($row->fee_currency))
				$t['festive_days_to'] = $row->festive_days_to;   	
	    	if(isset($row->take_away))
	    		$t['take_away'] = $row->take_away;
	    	if(isset($row->opening_hours))
	    		$t['opening_hours'] = $row->opening_hours;
	    	if(isset($row->delivery))
	    		$t['delivery'] = $row->delivery;
	    	 if(isset($row->desc))
	        	$t['article_body'] = $row->desc;
	    	//get metadata for place_Form_EditPlace
	    	if(isset($row->metadata))
	    	{
	    		$metadata = unserialize($row->metadata);
		    	if(isset($metadata['contact_email']))
		    		$t['contact_email'] = $metadata['contact_email'];
		    	if(isset($metadata['website']))
		    		$t['website'] = $metadata['website'];
		    	if(isset($metadata['fax']))
		    		$t['fax'] = $metadata['fax'];
		    	if(isset($metadata['phone']))
		    		$t['phone'] = $metadata['phone'];
	    	}
	    	
	    	//get vicinities data
    		$mVicinity = new place_Model_Vicinity();
    		$vicinityData = $mVicinity->getVicinitiesByPlaceId($row->id);
    		if(isset($vicinityData))
    		{
	    		$ids = $names = $dis = '';
		        foreach($vicinityData as $key => $ret)
		        {
		        	if($ids == '' )
		        	{
			    		$ids .=  $ret['vicinity_place_id'];
			    		$names .= $ret['vicinity_place_name']; 
			    		$dis .= $ret['distance'];
		        	}
		        	else
		        	{
		        		$ids .=  ','.$ret['vicinity_place_id'];
			    		$names .= ','. $ret['vicinity_place_name']; 
			    		$dis .= ','. $ret['distance'];
		        	}
		        }
		        $t['belong_to_ids'] = $ids;
		        $t['belong_to_names_submit'] = $names;
		        $t['distance'] = $dis;
	    	}
		}
//		die_a($t);
		return $t;
	}

	public function searchBelongTo($data, $part)
	{
    	$db = $this->getAdapter();
    	$sql = "SELECT p.id, p.name, p.unaccented_name FROM places p WHERE 1 ";
    	$sql .= " AND p.unaccented_name LIKE " . (string)$db->quote("%$part%",'STRING');
		if(!empty($data['rtype']))
			$sql .= " AND rtype = " . $db->quote($data['rtype'],'INTEGER');
		for($i = 0; $i < count($part); $i++)
			$sql .= " LIMIT 10";
		$ret = $db->query($sql);
        return $ret->fetchAll();
	}
	
	//TODO: check place has already been exits
	public function checkPlace($data)
	{
		$db = $this->getAdapter();
		$sql = "SELECT p.name FROM places p WHERE 1";
		$result = $db->query($sql);
		$ret = $result->fetchAll();
		foreach($ret as $p)
		{
			$p = (array)$p;
			if($p['name'] == $data)
				return false;
			else
				return true;
		}
	}
	
	public function getListBank($data)
	{
		$db = $this->getAdapter();
		if(isset($data))
        {
        	$type = implode(',', $data['type']);
        	$s = "SELECT name FROM places p WHERE p.type LIKE " . $db->quoteinto("'%$type%'","STRING");
    	 	foreach($data['type'] as $v )
    	 	{
    	 		$s .= " OR p.type LIKE " . $db->quoteinto("'%$v%'","STRING");
    	 	}
    	 	$results = $db->fetchAll($s);
    	 	return $results;
        }
	}
	//only used in importing data from excel
	public function insertAllRaw($data,$doValidate = false)
	{
		if(!empty($data['excelId']))
		{
			//require_once (APP_PATH.'/modules/user/Model/User.php');
			$keys = array('id', 'country_id','name','city_id','district_id','village_id',
	                      'article_id','type','rtype','longitude', 'area',
	                      'latitude','address5','address6', 'address7', 'address8',
	        	          'address9','other_name', 'status', 'poster_id',
	        	          'desc','article_id', 'built_year', 'opening_hours', 'close_by',
	        	          'fee', 'fee_basis', 'fee_currency', 'payment_method', 'rating', 
	        	          'rating_count', 'phone', 'fax', 'contact_email', 'website', 
						  'number_of_rooms', 'number_of_available_rooms', 'take_away',
						  'delivery', 'meals', 'festive_days_from', 'festive_days_to', 'metadata');
	        $t = clu_array_merge($keys, $data);
	        $t['fee_basis'] = isset($t['fee_basis']) ? $t['fee_basis'] : 'entrance';
	        $t['fee_currency'] = isset($t['fee_currency']) ? $t['fee_currency'] : 'VND';
	      	$t['unaccented_name'] = VN_unaccent($t['name']);
	
	      	$mCity = new place_Model_City();
	        $mDistrict = new place_Model_District();
	        $mVillage = new place_Model_Village();
	        $mCategory = new category_Model_Category();
			$mCategory->setTables('place');
	        $cityName = $mCity->getCityName($t['city_id']);
	        $districtName = $mDistrict->getDistrictName($t['district_id']);
	        $villageName = $mVillage->getVillageName($t['village_id']);
	        $rtypeName = $mCategory->getCategoryName($t['rtype']);
	        $typeName = $mCategory->getCategoryName($t['type']);
	        $a['city_name'] = $cityName['city_name'];
	        $a['district_name'] = $districtName['district_name'];
	        $a['village_name'] = $villageName['village_name'];
	        $a['rtype_name'] = $rtypeName['name'];
	        $a['type_name'] = $typeName['name'];
	        $uModel = new user_Model_User();
	        $u = $uModel->findByPrimary($t['poster_id']);
	    	$a['poster_name'] = $u->name;
	        $t['metadata'] = serialize($a);
	       	return $this->insert($t);
		}
	}
	
	public function relatedEvent($placeId, $eventId, $rowId)
	{
		$data = array();
		$data['event_id'] = $eventId;
		if($rowId == null)
		{
			$row = $this->findByPrimary($placeId);
			$this->saveRaw($row, $data, $placeId, false);
		}
		else
		{
			//update event_id for new place_id
			$row = $this->findByPrimary($placeId);
			$relatedEventId = explode(',', $row->metadata);
			foreach($relatedEventId as $e)
				if($data['event_id'] != $e)
					$this->saveRaw($row, $data, $placeId, false);			
			
			//delete related_event_id of old place_id
			$data['place_id'] = $rowId;
			$row = $this->findByPrimary($rowId);
			$this->saveRaw($row, $data, $rowId, false);
			
		}
	}
	
	public function relatedTour($placeId, $tourId, $rowId)
	{
		$data = array();
		$data['tour_id'] = $tourId;
		if($rowId == null)
		{
			$row = $this->findByPrimary($placeId);
			$this->saveRaw($row, $data, $placeId, false);
		}
		else
		{
			//update event_id for new place_id
			$row = $this->findByPrimary($placeId);
			if(!empty($row))
			{
				$relatedEventId = explode(',', $row->metadata);
				foreach($relatedEventId as $e)
					if($data['tour_id'] != $e)
						$this->saveRaw($row, $data, $placeId, false);			
			}
			/*
			//delete related_tour_id of old place_id
			$data['place_id'] = $rowId;
			$row = $this->findByPrimary($rowId);
			$this->saveRaw($row, $data, $rowId, false);
			*/
		}
	}
	
	public function deleteRelatedTourId($id, $rowId)
	{
		//delete related_tour_id of old place_id
		$data['tour_id'] = $id;
		$data['place_id'] = $rowId;
		$row = $this->findByPrimary($rowId);
		$this->saveRaw($row, $data, $rowId, false);
	}
	
	public function updateDbAfterInsert($cityId,$districtId, $rtype, $type)
	{
		$mCategory = new category_Model_Category();
		$mCategory->setTables('place');
		try{
			$mCity = new place_Model_City();
			$city = $mCity->findByPrimary($cityId);
			$metadataCity = unserialize($city['metadata']);
			$metadataCity['place_count']['number_of_places'] = (integer) $metadataCity['place_count']['number_of_places'] + 1;
			if(!empty($rtype))
	    	{
		        if(isset($metadataCity['place_count'][$rtype]))
					$metadataCity['place_count'][$rtype] = (integer) $metadataCity['place_count'][$rtype] + 1;
		        else
		        	$metadataCity['place_count'][$rtype] = 1;
	    	}
	    	
	    	if(isset($type))
	    	{
	    		if(!is_array($type))
					$type = explode(',', $type);
	    		foreach($type as $k => $v)
	    		{
			        if(isset($metadataCity['place_count'][$v]))
						$metadataCity['place_count'][$v] = (integer) $metadataCity['place_count'][$v] + 1;
					else
						$metadataCity['place_count'][$v] = 1;
	    		}
	    	}
			$city['metadata'] = serialize($metadataCity);
			$city->save();
		}
		catch (Exception $e)
		{
			$db->rollBack();
			$this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(903);
		}
		
		if($districtId)
		{
			try{
				$mDistrict = new place_Model_District();
				$district = $mDistrict->findByPrimary($districtId);
				if(isset($district->metadata))
				{
					$metadataDistrict = unserialize($district->metadata);
					$metadataDistrict['place_count']['number_of_places'] = (integer) $metadataDistrict['place_count']['number_of_places'] + 1;
					if(!empty($rtype))
			    	{
				        if(isset($metadataDistrict['place_count'][$rtype]))
							$metadataDistrict['place_count'][$rtype] = (integer) $metadataDistrict['place_count'][$rtype] + 1;
				        else
				        	$metadataDistrict['place_count'][$rtype] = 1;
			    	}
			    	
			    	if(isset($type))
			    	{
			    		if(!is_array($type))
							$type = explode(',', $type);
			    		foreach($type as $k => $v)
			    		{
					        if(isset($metadataDistrict['place_count'][$v]))
								$metadataDistrict['place_count'][$v] = (integer) $metadataDistrict['place_count'][$v] + 1;
							else
								$metadataDistrict['place_count'][$v] = 1;
			    		}
			    	}
					$district['metadata'] = serialize($metadataDistrict);
				}
				$district->save();
			}
			catch(Exception $e)
			{
				$db->rollBack();
	            $this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(904);
			}
		}
		
		/*
		 * update count category
		 */
    	if(isset($rtype))
    		$this->increaseCategory($rtype);
    	if(isset($type))
    	{
    		if(!is_array($type))
				$type = explode(',', $type);
    		foreach($type as $k => $v)
    		{
    			$this->increaseCategory($v);
    		}
    	}
    	
	}
	/*
	 * updateDbAfterUpdate() function
	 * @Param: $p is db object of one Row
	 * 		   $data: Form Data
	 */
	//TODO: 
	public function updateDbAfterUpdate($p, $cityId, $districtId, $rtype, $type)
	{
		//city_id change
		if(!empty($cityId) && $p->city_id != $cityId)
		{
			try{
				$mCity = new place_Model_City();
				$this->updateDbAfterDelete($p->city_id, null, null, null);
				$city = $mCity->findByPrimary($cityId);
				$metadataCity = unserialize($city['metadata']);
				if(isset($metadataCity['place_count']['number_of_places']))
					$metadataCity['place_count']['number_of_places'] = (integer) $metadataCity['place_count']['number_of_places'] + 1;
				$city['metadata'] = serialize($metadataCity);
				$city->save();
			}
			catch (Exception $e)
			{
				$db->rollBack();
				$this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(903);
			}
		}
		
		//District change
		if(!empty($districtId) && $p->district_id != $districtId)
		{
			try{
				$mDistrict = new place_Model_District();
				$this->updateDbAfterDelete($p->city_id, $p->district_id, null, null);
				$district = $mDistrict->findByPrimary($districtId);
				$metadataDistrict = unserialize($district['metadata']);
				$metadataDistrict['place_count']['number_of_places'] = (integer) $metadataDistrict['place_count']['number_of_places'] + 1;
				$district['metadata'] = serialize($metadataDistrict);
				$district->save();
			}
			catch(Exception $e)
			{
				$db->rollBack();
	            $this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(904);
			}
		}
		
		// $rtype change
		if($p->rtype != $rtype)
		{
			$this->updateDbAfterDelete($p->city_id, null, $p->rtype, null);
			$this->increaseCategory($rtype);
    		
    		//type change
    		$newType = explode(',', $type);
			$oldType = explode(',', $p->type);
		
			foreach($newType as $t)
    		{
    			//if $newType not in $oldType then increase by one
    			if(!in_array($t, $oldType))
    				$this->increaseCategory($t);
    		}
    		
    		foreach($oldType as $o)
			{
				//if $oldType not in $newType then decrease by one im catwegoruy
    			if(!in_array($o, $newType))
    				$this->updateDbAfterDelete($p->city_id, null, null, $o);
			}
		}
		
		//$type change		
		if(isset($type))
		{
			$newType = explode(',', $type);
			$oldType = explode(',', $p->type);
			foreach($newType as $t)
    		{
    			//if $newType not in $oldType then increase by one
    			if(!in_array($t, $oldType))
    				$this->increaseCategory($t);
    		}
    		
    		foreach($oldType as $o)
			{
				//if $oldType not in $newType then decrease by one im category
    			if(!in_array($o, $newType))
    				$this->updateDbAfterDelete($p->city_id, null, null, $o);
			}
		}
	}
	
	/*
	 * Delete
	 */
	public function updateDbAfterDelete($cityId, $districtId, $rtype, $type)
	{
		try{
			$mCity = new place_Model_City();
			$city = $mCity->findByPrimary($cityId);
			$metadataCity = unserialize($city['metadata']);
			$metadataCity['place_count']['number_of_places'] = (integer) $metadataCity['place_count']['number_of_places'] - 1;
			if(!empty($rtype))
	    	{
		        if(isset($metadataCity['place_count'][$rtype]))
					$metadataCity['place_count'][$rtype] = (integer) $metadataCity['place_count'][$rtype] - 1;
	    	}
	    	
	    	if(isset($type))
	    	{
	    		if(!is_array($type))
					$type = explode(',', $type);
	    		foreach($type as $k => $v)
	    		{
			        if(isset($metadataCity['place_count'][$v]))
						$metadataCity['place_count'][$v] = (integer) $metadataCity['place_count'][$v] - 1;
	    		}
	    	}
	    	
			$city['metadata'] = serialize($metadataCity);
			$city->save();
		}
		catch (Exception $e)
		{
			$db->rollBack();
			$this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(903);
		}
		
		if($districtId)
		{
			try{
			
				$mDistrict = new place_Model_District();
				$district = $mDistrict->findByPrimary($districtId);
				$metadataDistrict = unserialize($district['metadata']);
				$metadataDistrict['place_count']['number_of_places'] = (integer) $metadataDistrict['place_count']['number_of_places'] - 1;
				if(!empty($rtype))
		    	{
			        if(isset($metadataDistrict['place_count'][$rtype]))
						$metadataDistrict['place_count'][$rtype] = (integer) $metadataDistrict['place_count'][$rtype] - 1;
		    	}
		    	
		    	if(isset($type))
		    	{
		    		if(!is_array($type))
						$type = explode(',', $type);
		    		foreach($type as $k => $v)
		    		{
				        if(isset($metadataDistrict['place_count'][$v]))
							$metadataDistrict['place_count'][$v] = (integer) $metadataDistrict['place_count'][$v] - 1;
		    		}
		    	}
				$district['metadata'] = serialize($metadataDistrict);
				$district->save();
			}
			catch(Exception $e)
			{
				$db->rollBack();
	            $this->viewParams['errorMessage'] = $e->getMessage() . "<br/>". t(904);
			}
		}
		
		/*
		 * update count category
		 */
		
    	if(isset($rtype))
    		$this->decreaseCategory($rtype);
    	
    	if(isset($type))
    	{
    		if(!is_array($type))
				$type = explode(',', $type);
    		foreach($type as $k => $v)
    		{
    			$this->decreaseCategory($v);
    		}
    	}
	}
	
	/*
	 * @param: $categoryId is rtype or type
	 */
	public function increaseCategory($categoryId)
	{
		$mCategory = new category_Model_Category();
		$mCategory->setTables('place');
		$category = $mCategory->findByPrimary($categoryId);
		if(!empty($category))
		{
    		$metadata = unserialize($category['metadata']);
	        if(isset($metadata['total']))
				$metadata['total'] = (integer) $metadata['total'] + 1;
			else
				$metadata['total'] = 1;
    		
    		$category['metadata'] = serialize($metadata);
    		$category->save();
		}
	}
	
	public function decreaseCategory($categoryId)
	{
		$mCategory = new category_Model_Category();
		$mCategory->setTables('place');
		$category = $mCategory->findByPrimary($categoryId);
		if(!empty($category))
		{
    		$metadata = unserialize($category['metadata']);
	        if(isset($metadata['total']))
				$metadata['total'] = (integer) $metadata['total'] - 1;
    		
    		$category['metadata'] = serialize($metadata);
    		$category->save();
		}
	}
	
	  /**
         * A broader search than findByPrimary()
         * ** Only works for simple & quick search **
         * This is a kinda a hack? TODO: merge it into search functionality
         * $key : name
         * $val : value of user Name
         * $valType: "INTEGER | STRING"
         * $searchType: equal or like
         
    public function findByExpression($key, $val, $valType, $searchType)
        {
            if ($val === null)
            return null;
        else
        {
                $tmp = $this->getAdapter()->quote($val, $valType);
                $sql = $key . " ";
                        if ($searchType == "equals")
                                $sql = $sql . "=" . $tmp;
                        elseif($searchType == "like")
                                $sql = $sql . "like %".$tmp."%";                
                    return $this->fetchRow($sql);
        }
        }
	*/ 
	public function advancedFind($data)
	{
		$sql = "1 ";
        foreach ($data as $cond)
        {
        	$tmp = $this->getAdapter()->quote($cond['val'], $cond['valType']);
            $sql = $sql . " AND " . $cond['key'] . " ";
            if ($cond['searchType'] == "equals")
            	$sql = $sql . "=" . $tmp;
            elseif($cond['searchType'] == "like")
            	$sql = $sql . "like %".$tmp."%";                
        }
		return $this->fetchRow($sql);
	}
}
?>
